<?php
namespace ITSociaal\Themes\Houtgrutter\Laura;

use ITSociaal\Themes\Houtgrutter\WordPressBase;
use WP_Query;

class Advertentie extends WordPressBase
{
	/** @var \ITSociaal\Themes\Houtgrutter\Laura\Util */
	protected $util;

	/** @var \ITSociaal\Themes\Houtgrutter\WordPressInterface */
	protected $wpi;

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractContent($post)
	{
		return [
			/* Cannot use `apply_filters("the_content")` here,
			 * because that's where shopp injects its content.
			 * Any shortcodes in the post will be shown as is.
			 */
			"content" => $post->post_content,
		];
	}

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractHave($post)
	{
		return [
			"have_ad" => boolval($post->ID),
		];
	}

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractImage($post)
	{
		$wp = $this->getWP();
		$attr = [
			"class" => "advertentie-featured",
		];
		$have_image = $wp->has_post_thumbnail($post);
		$image = $have_image
			? $wp->get_the_post_thumbnail($post, "full", $attr) : "";

		return compact("have_image", "image");
	}

	/**
	 * @param object $post
	 *
	 * @return array
	 */
	protected function extractTitle($post)
	{
		return [
			"title" => $post->post_title,
		];
	}

	/**
	 * Search the latest post in the "Advertenties" category
	 *
	 * @see /wp-admin/term.php?taxonomy=category&tag_ID=19&post_type=post
	 *
	 * @return \WP_Query
	 */
	protected function createQuery()
	{
		return $this->getUtil()->createObject(
			WP_Query::class,
			[
				'cat' => 19,
				'post_status' => 'publish',
				'posts_per_page' => 1,
				'order' => 'DESC',
				'orderby' => 'ID',
			]);
	}

	/**
	 * @return object
	 */
	protected function getPost()
	{
		// array -> generator -> array. I'm weird
		return iterator_to_array(
			$this->getUtil()->generatePostsFromWpQuery(
				$this->createQuery()
			),
			false //use_keys
		)[0] ?: $this->getUtil()->createEmptyPost();
	}

	/**
	 * @return \ITSociaal\Themes\Houtgrutter\Laura\Util
	 */
	protected function getUtil()
	{
		return $this->util;
	}

	/**
	 * Wraps callables into automatically bound anonymous functions
	 *
	 * Should probably be moved elsewhere but it's not an issue yet.
	 * If you move this method, remember to manually bind it to the
	 * right context so protected and private methods can be called.
	 *
	 * @param array $callables
	 *
	 * @return \Closure[]
	 */
	protected function wrapCallables(array $callables)
	{
		return array_map(
			function($callable) {
				return function(...$args) use ($callable) {
					return $callable(...$args);
				};
			},
			$callables
		);
	}

	/**
	 * Retrieve data to use in a template
	 *
	 * @param \ITSociaal\Themes\Houtgrutter\Laura\Advertentie $self
	 * @param \ITSociaal\Themes\Houtgrutter\Laura\Util        $util
	 *
	 * @return object
	 */
	public static function createContext(Advertentie $self=null, Util $util=null)
	{
		$util = $util ?: new Util();
		$self = $self ?: new static($util);

		return $self
			->getData();
	}

	/**
	 * @param \ITSociaal\Themes\Houtgrutter\Laura\Util $util
	 */
	public function __construct(Util $util)
	{
		$this->util = $util;
	}

	/**
	 * Retrieve data to use in a template
	 *
	 * @return object
	 */
	public function getData()
	{
		$util = $this->getUtil();

		return (object)array_merge(...iterator_to_array(
			$util->generateResultPerMethod(
				$this->wrapCallables(
					$util->getCallablesFromPrefixedMethods(
						$this, "extract", true
					)
				),
				$this->getPost()
			)
		));
	}
}

/* vi:set ts=4 sw=4 noet: */
